forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1import type { DocsResponse } from '#shared/types'
2import { assertValidPackageName } from '#shared/utils/npm'
3import { parsePackageParam } from '#shared/utils/parse-package-param'
4import { generateDocsWithDeno } from '#server/utils/docs'
5
6export default defineCachedEventHandler(
7 async event => {
8 const pkgParam = getRouterParam(event, 'pkg')
9 if (!pkgParam) {
10 // TODO: throwing 404 rather than 400 as it's cacheable
11 throw createError({ statusCode: 404, message: 'Package name is required' })
12 }
13
14 const { packageName, version } = parsePackageParam(pkgParam)
15
16 if (!packageName) {
17 // TODO: throwing 404 rather than 400 as it's cacheable
18 throw createError({ statusCode: 404, message: 'Package name is required' })
19 }
20 assertValidPackageName(packageName)
21
22 if (!version) {
23 // TODO: throwing 404 rather than 400 as it's cacheable
24 throw createError({ statusCode: 404, message: 'Package version is required' })
25 }
26
27 let generated
28 try {
29 generated = await generateDocsWithDeno(packageName, version)
30 } catch (error) {
31 // eslint-disable-next-line no-console
32 console.error(`Doc generation failed for ${packageName}@${version}:`, error)
33 return {
34 package: packageName,
35 version,
36 html: '',
37 toc: null,
38 status: 'error',
39 message: 'Failed to generate documentation. Please try again later.',
40 } satisfies DocsResponse
41 }
42
43 if (!generated) {
44 return {
45 package: packageName,
46 version,
47 html: '',
48 toc: null,
49 status: 'missing',
50 message: 'Docs are not available for this package. It may not have TypeScript types.',
51 } satisfies DocsResponse
52 }
53
54 return {
55 package: packageName,
56 version,
57 html: generated.html,
58 toc: generated.toc,
59 status: 'ok',
60 } satisfies DocsResponse
61 },
62 {
63 maxAge: 60 * 60, // 1 hour cache
64 swr: true,
65 getKey: event => {
66 const pkg = getRouterParam(event, 'pkg') ?? ''
67 return `docs:v2:${pkg}`
68 },
69 },
70)